package com.wontube.client.remote;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

import com.wontube.client.conf.ServerEnvironment;
import com.wontube.client.io.IObjectProtocol;
import com.wontube.client.io.ProtocolProxyFactory;
import com.wontube.client.log.MinLoggerFactory;
import com.wontube.client.log.MinLoggerFactory.MinLogger;
import com.wontube.client.pub.ServerResponse;


/**
 * @author yuechao
 * 
 */
public final class DefaultInvocationHandler implements InvocationHandler {
	private static final MinLogger logger = MinLoggerFactory.getLogger(DefaultInvocationHandler.class);
	private ProxyClient client;

	public DefaultInvocationHandler(ProxyClient client) {
		this.client = client;
	}

	/*
	 * @see core.remote.IInvocationHandler#invoke(java.lang.Object,
	 * java.lang.reflect.Method, java.lang.Object[])
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) {
		Class<?> clazz = method.getDeclaringClass();
		if (clazz == Object.class) {
			// 不要使用服务器代理Object的方法，这是无意义的
			try {
				return method.invoke(proxy.getClass(), args);
			} catch (Exception e) {
				logger.error(e.toString());
				return null;
			}
		}

		// 处理包前缀
		String clazzName = method.getDeclaringClass().getName();
		clazzName = ServerEnvironment.processInterfaceName(clazzName);
		
		String methodName = method.getName();
		Type retType = method.getGenericReturnType();
		IObjectProtocol protocol = ProtocolProxyFactory.createProtocol(this.client.getDataFormat());
		if (protocol == null) {
			throw new RuntimeException("Not supported data format: " + this.client.getDataFormat());
		}
		
		try {
			String content = this.client.invoke(protocol, clazzName, methodName, args);
			ServerResponse response = new ServerResponse();
			if(content != null){
				response.fromJsonString(content);
			}
			
			this.client.setDone(response.isDone());
			this.client.setHeaders(response.getHeaders());

			if (response.isDone()) {
				ServerEnvironment.lastClientSessionId = response.getSessionId();
				if (retType != void.class) {
					content = response.getContent();
					return protocol.toObject(content, retType);
				}
			} else {
				this.client.setErrorMsg(response.getContent());
			}
		} catch (Exception e) {
			logger.error(e.toString());
			this.client.setDone(false);
			this.client.setErrorMsg(e.getMessage());
		}

		return null;
	}
}
